/* 算法实现模板 */
import TDom from "../../../common/TDom";
import AlgorithmBase from "./AlgorithmBase";
import { txtToMatrix } from "../../../common/Common";
import TVisual from "../../../common/TVisual";
import TCommon from "../../../common/TCommon";
import TArray from "../../../common/TArray";

class KNNDatingTest extends AlgorithmBase{
  constructor(){
    super('KNNDatingTest');

    this.datasetUrl     = `${this.homepage}/data/ml-in-action/ch2/datingTestSet.dat`;
    this.descriptionUrl = `${this.homepage}/data/ml-in-action/ch2/README.md`;
  }

  initDataset(){
    this.loadRemoteDataset();
  }

  clearData(){
    this.dataset = undefined;
  }

  initCollectUI(){
    TDom.createButton(
      this.domElementList.collect, 
      "获取服务器数据", 
      this.loadRemoteDataset.bind(this)
    );
    // 添加文件选择器
    this.fileSelector = TDom.createFileSelector(
      this.domElementList.collect,
      this.handleFileChange.bind(this)
    );
    // 隐藏并设置文文件单选
    this.fileSelector.hidden   = true;
    this.fileSelector.multiple = false;
    TDom.createButton(
      this.domElementList.collect, 
      "使用本地数据", 
      this.loadLocalDataset.bind(this)
    );


    this.collectDiv = TDom.createDiv(this.domElementList.collect);
  }

  initPrepareUI(){
    TDom.createButton(
      this.domElementList.prepare,
      "归一化特征值",
      this.prepare.bind(this)
    )
    this.prepareTips = TDom.createLabel(this.domElementList.prepare, "");
    this.prepareDiv  = TDom.createDiv(this.domElementList.prepare);
  }

  initTestUI(){
    const btnDoTest       = document.createElement('button');
    btnDoTest.innerText   = '开始测试';
    // btnDoTest.addEventListener('click', this.doTest.bind(this));
    const ratioLabel      = document.createElement('label');
    ratioLabel.innerText  = "测试百分比";
    const ratioInput      = document.createElement('input');
    ratioInput.type       = 'number';
    ratioInput.value      = 50;
    const resultLabel     = document.createElement('label');
    const resultDiv       = document.createElement('div');

    this.domElementList.test.innerHTML = '';
    this.domElementList.test.appendChild(ratioLabel);
    this.domElementList.test.appendChild(ratioInput);
    this.domElementList.test.appendChild(btnDoTest);
    this.domElementList.test.appendChild(resultLabel);
    this.domElementList.test.appendChild(resultDiv);

    this.ratioInput   = ratioInput;
    this.resultLabel  = resultLabel;
    this.resultDiv    = resultDiv;
  }

  // 从服务器获取数据
  loadRemoteDataset(){
    this.collect(this.datasetUrl);
  }
  // 从本地读取数据
  loadLocalDataset(){
    this.fileSelector.click();
  }
  // 处理文件选择
  handleFileChange(event){
    const files = event.target.files;

    let reader = new FileReader();
    reader.onload = (e) => {      
      this.collect(e.target.result);
    };
    reader.readAsDataURL(files[0])
  }
  // 收集数据
  collect(url){
    TDom.getDataFromUrl(url, (txt)=>{
      this.dataset = txtToMatrix(txt);

      TVisual.renderMatrix(this.dataset, this.collectDiv);
    });
  }
  // 准备数据
  prepare(){
    const dataset = this.dataset;
    if(!dataset){
      this.prepareTips.innerText = "未加载任何数据集.";
    }

    this.trainDS = TCommon.loadDataset(dataset);
    this.trainDS.Mat = TCommon.autoNorm(this.trainDS.Mat);

    TVisual.renderMatrix(this.trainDS.Mat.toArray(), this.prepareDiv);
    this.prepareTips.innerText = "数据准备完毕.";    

    this.analysis();
  }
  
  // 分析数据
  analysis(){
    const trainDS = this.trainDS;
    if(!trainDS) return;

    this.pointStyleDict = TVisual.createRandomPointStyleDict(this.trainDS.Labels);
    TVisual.renderMat(
      trainDS.Mat, 
      this.analysisDiv,
      trainDS.Labels,
      {},
      this.pointStyleDict
    );
  }

  // 测试算法
  test(){
    const testDS  = this.trainDS;
    if(!testDS){
      this.resultLabel.innerText=`训练数据未准备好...`;
      return;
    } 

    let ratio     = parseFloat(this.ratioInput.value);

    // if(ratio < 10 || ratio > 90){
    //   ratio = 50;
    //   this.ratioInput.value = ratio;
    // }

    // const m           = Math.floor(ratio * testDS.Mat.length / 100);
    // const testMat     = testDS.Mat.slice(0, m);
    // const testLabels  = testDS.Labels.slice(0, m);
    // const trainMat    = testDS.Mat.slice(m);
    // const trainLabels = testDS.Labels.slice(m);
    // let errResult     = new Matrix.Matrix();

    // let errCount = 0;
    // for(let i=0; i < m; i++){
    //   const classifierResult = classfy0(testMat[i], trainMat, trainLabels, 3);

    //   if( parseInt(testLabels[i]) !== parseInt(classifierResult)){
    //     // console.log(`误分类点:${i},实际值${testLabels[i]},预测值${classifierResult}`);
    //     errResult.push([i, ...testMat[i], testLabels[i], classifierResult]);
    //     errCount ++;
    //   }
    // }

    // this.resultLabel.innerText=`错误率:${(errCount / m).toFixed(6)}`;
  }
}


export default KNNDatingTest;